<!DOCTYPE html>
<html lang="zh-cn">
<head>
  <meta charset="UTF-8">
  <title>线性代数-矩阵</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }
    body {
      padding: 50px;
    }
    .input-wrap {
      display: inline-block;
    }
    .input-wrap > h1 {
      font-size: 20px;
    }
    .input-wrap > textarea {
      display: block;
      width: 400px;
      height: 200px;
      margin-right: 20px;
      margin-top: 10px;
      padding: 10px;
      border: 1px solid #aaa;
      font-size: 18px;
      line-height: 22px;
      font-family: verdana, cursive, sans-serif;
      letter-spacing: 2px;
      outline: none;
    }
    .input-wrap > input {
      margin-top: 10px;
      margin-right: 10px;
      display: inline-block;
      width: 100px;
      padding: 5px 10px;
      border: 1px solid #aaa;
      border-radius: 5px;
      font-size: 15px;
      font-family: verdana, cursive, sans-serif;
      outline: none;
    }
    .trigger {
      padding: 5px 8px;
      border: 1px solid #7bd87e;
      background-color: #c5f5c7;
      cursor: pointer;
      border-radius: 4px;
      outline: none;
      margin-right: 10px;
    }
    .trigger[disabled] {
      background-color: #cfffd1;
      cursor: not-allowed;
    }
    .trigger:hover {
      background-color: #cfffd1;
    }
    .trigger:active {
      background-color: #9cdb9f;
    }
    #formula {
      display: inline-block;
    }
    input[type=radio] {
      position: absolute;
      visibility: hidden;
      z-index: -1;
    }
    input[type=radio] + label {
      position: relative;
      display: inline-block;
      cursor: pointer;
      padding-left: 30px;
      margin-right: 20px;
    }
    input[type=radio] + label::before {
      content: " ";
      position: absolute;
      top: 50%;
      left: 0;
      transform: translateY(-50%);
      width: 20px;
      height: 20px;
      box-sizing: border-box;
      border: 1px solid #7bd87e;
      border-radius: 50%;
      vertical-align: middle;
    }
    input[type=radio] + label::after {
      content: " ";
      position: absolute;
      top: 50%;
      left: 5px;
      transform: translateY(-50%) scale(0);
      width: 10px;
      height: 10px;
      background-color: #7bd87e;
      border-radius: 50%;
      transition: transform 300ms cubic-bezier(0.68, -0.55, 0.27, 1.55);
    }
    input[type=radio]:checked + label::after {
      transform: translateY(-50%) scale(1);
    }
    .row {
      margin-top: 20px;
    }

  </style>
  <script>
    window.MathJax = {
      tex: { inlineMath: [] },
      loader: { load: ['input/tex', 'output/svg'] },
      // svg输出配置
      svg: {
        scale: 1,                      // global scaling factor for all expressions
        minScale: .5,                  // smallest scaling factor to use
        mtextInheritFont: false,       // true to make mtext elements use surrounding font
        merrorInheritFont: true,       // true to make merror text use surrounding font
        mathmlSpacing: false,          // true for MathML spacing rules, false for TeX rules
        skipAttributes: {},            // RFDa and other attributes NOT to copy to the output
        exFactor: .5,                  // default size of ex in em units
        displayAlign: 'center',        // default for indentalign when set to 'auto'
        displayIndent: '0',            // default for indentshift when set to 'auto'
        fontCache: 'local',            // or 'global' or 'none'
        localID: null,                 // ID to use for local font cache (for single equation processing)
        internalSpeechTitles: true,    // insert <title> tags with speech content
        titleID: 0                     // initial id number to use for aria-labeledby titles
      },
      options: {
        // 不自动渲染页面上的公式
        skipHtmlTags: ['body'],
        renderActions: {
          // 禁止右键菜单
          // addMenu: []
        },
      },
      startup: {
        ready: () => {
          console.log('MathJax is loaded, but not yet initialized')
          MathJax.startup.defaultReady()
          console.log('MathJax is initialized, and the initial typeset is queued')
          document.querySelectorAll('.trigger').forEach(ele => ele.disabled = false)
        }
      }
    }
  </script>
  <script async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js"></script>
</head>
<body>
<div class="input-wrap">
  <h1>矩阵1</h1>
  <textarea id="input1" placeholder="请输入一串逗号分隔的数字">1,2,3,4,5,6</textarea>
  <input type="number" id="m1" min="0" placeholder="行数">
  <input type="number" id="n1" min="0" placeholder="列数">
</div>
<div class="input-wrap">
  <h1>矩阵2</h1>
  <textarea id="input2" placeholder="请输入一串逗号分隔的数字">9,8,7,6,5,4</textarea>
  <input type="number" id="m2" min="0" placeholder="行数">
  <input type="number" id="n2" min="0" placeholder="列数">
</div>
<div class="row">
  <input type="radio" name="order" id="row-order" value="row" checked>
  <label for="row-order">
    <span>行主序（Direct3D）</span>
  </label>
  <input type="radio" name="order" id="column-order" value="column">
  <label for="column-order">
    <span>列主序（OpenGL）</span>
  </label>
</div>
<div class="row">
  <button id="btn-transpose" class="trigger" disabled>矩阵1转置</button>
  <button id="btn-plus" class="trigger" disabled>矩阵相加</button>
  <button id="btn-minus" class="trigger" disabled>矩阵相减</button>
  <button id="btn-multiply" class="trigger" disabled>矩阵相乘</button>
  <button id="btn-adjugate" class="trigger" disabled>获取矩阵1的伴随矩阵</button>
  <button id="btn-inverse" class="trigger" disabled>矩阵1求逆</button>
</div>
<div class="wrap">
  <div id="formula"></div>
  <div id="output"></div>
</div>

<script>
  (function () {

    // 行列式
    class Determinant {
      constructor (numList, order) {
        numList = numList || []
        let itemList = [[]]
        if (numList && numList.length) {
          itemList = this.getItemList(numList, order)
        }
        this.numList = numList
        this.itemList = itemList
      }

      // 根据数字列表获取二维数组
      getItemList (numList, order) {
        const size = Math.sqrt(numList ? numList.length : 0) // 阶数
        if (size.toString().indexOf('.') !== -1) {
          throw Error('行列式格式错误')
        }
        let i, j, itemList, subItemList
        itemList = new Array(size)
        if (order === 'row') {  // 行主序
          for (i = 0; i < size; i++) {
            subItemList = new Array(size)
            for (j = 0; j < size; j++) {
              subItemList[j] = numList[i * size + j]
            }
            itemList[i] = subItemList
          }
        }
        else if (order === 'column') {  // 列主序
          for (i = 0; i < size; i++) {
            subItemList = new Array(size)
            for (j = 0; j < size; j++) {
              subItemList[j] = numList[j * size + i]
            }
            itemList[i] = subItemList
          }
        }
        return itemList
      }

      // 获取行列式在i行j列的元素的余子式
      getMinor (i, j, itemList) {
        itemList = itemList || this.itemList
        const size = this.itemList.length
        const minorItemList = []
        let _i, _j, subItemList
        for (_i = 0; _i < size; _i++) {
          // 不同行
          if (_i !== i) {
            subItemList = []
            for (_j = 0; _j < size; _j++) {
              // 且不同列
              if (_j !== j) {
                subItemList.push(itemList[_i][_j])
              }
            }
            minorItemList.push(subItemList)
          }
        }
        return minorItemList
      }

      // 获取行列式在i行j列的元素的代数余子式
      getCofactor (i, j, itemList) {
        itemList = itemList || this.itemList
        return Math.pow(-1, i + j) * this.getValue(this.getMinor(i, j, itemList))
      }

      // 获取行列式的值
      getValue (itemList) {
        itemList = itemList || this.itemList
        const size = itemList.length
        if (size === 1) {
          return itemList[0][0]
        }
        else if (size === 2) {
          return itemList[0][0] * itemList[1][1] - itemList[0][1] * itemList[1][0]
        }
        else if (size === 3) {
          return (
            itemList[0][0] * itemList[1][1] * itemList[2][2]
            + itemList[0][1] * itemList[1][2] * itemList[2][0]
            + itemList[0][2] * itemList[1][0] * itemList[2][1]
            - itemList[0][2] * itemList[1][1] * itemList[2][0]
            - itemList[0][0] * itemList[1][2] * itemList[2][1]
            - itemList[0][1] * itemList[1][0] * itemList[2][2]
          )
        }
        else if (size > 3) {
          let i = 0, sum = 0
          // 展开第一列
          for (i = 0; i < size; i++) {
            // aij * Aij
            sum += itemList[i][0] * this.getCofactor(this.getMinor(i, 0, itemList))
          }
          return sum
        }
      }

      // 根据字符串获取实例
      static fromArrayStr (str, order) {
        const numList = []
        str.split(',').forEach(v => v && numList.push(Number(v.trim())))
        return new Determinant(numList, order)
      }

      // 根据二维数组获取实例
      static fromItemList (itemList) {
        const determinant = new Determinant()
        determinant.itemList = itemList
        return determinant
      }
    }

    // 矩阵
    class Matrix {
      constructor (numList, m, n, order) {
        numList = numList || []
        m = m || 0
        n = n || 0
        let itemList = [[]]
        if (m && n && m * n === numList.length) {
          itemList = Matrix.getItemList(numList, m, n, order)
        }
        this.itemList = itemList
        this.numList = numList
        this.m = m
        this.n = n
      }

      // 根据数字列表获取m行n列的二维数组
      static getItemList (numList, m, n, order) {
        if (!(m && n && m * n === numList.length)) {
          throw Error('矩阵格式错误')
        }
        let i, j, itemList, subItemList
        itemList = new Array(m)
        if (order === 'row') {  // 行主序
          for (i = 0; i < m; i++) {
            subItemList = new Array(n)
            for (j = 0; j < n; j++) {
              subItemList[j] = numList[i * n + j]
            }
            itemList[i] = subItemList
          }
        }
        else if (order === 'column') {  // 列主序
          for (i = 0; i < m; i++) {
            subItemList = new Array(n)
            for (j = 0; j < n; j++) {
              subItemList[j] = numList[j * m + i]
            }
            itemList[i] = subItemList
          }
        }
        return itemList
      }

      // 获取矩阵的转置
      getTransposedMatrix () {
        const itemList = this.itemList
        const m = this.m
        const n = this.n
        const newItemList = new Array(n)
        let i, j, subItemList
        for (i = 0; i < n; i++) {
          subItemList = new Array(m)
          for (j = 0; j < m; j++) {
            subItemList[j] = itemList[j][i]
          }
          newItemList[i] = subItemList
        }
        return Matrix.fromItemList(newItemList)
      }

      // 矩阵相加
      plus (matrix, minus) {
        if (this.m === matrix.m && this.n === matrix.n) {
          const itemList = JSON.parse(JSON.stringify(this.itemList))
          let i, j
          for (i = 0; i < this.m; i++) {
            for (j = 0; j < this.n; j++) {
              itemList[i][j] = minus ? this.itemList[i][j] - matrix.itemList[i][j] : this.itemList[i][j] + matrix.itemList[i][j]
            }
          }
          return Matrix.fromItemList(itemList)
        }
        else {
          throw new Error('不是同型矩阵，无法相加')
        }
      }

      // 矩阵相减
      minus (matrix) {
        return this.plus(matrix, true)
      }

      // 矩阵相乘
      multiply (matrix) {
        if (this.n === matrix.m) {
          const m = this.m
          const p = this.n
          const n = matrix.n
          let i, j, k, sum
          const itemList1 = this.itemList
          const itemList2 = matrix.itemList
          const newItemList = new Array(m)
          let subItemList
          for (i = 0; i < m; i++) {
            subItemList = new Array(n)
            for (j = 0; j < n; j++) {
              sum = 0
              for (k = 0; k < p; k++) {
                sum += itemList1[i][k] * itemList2[k][j]
              }
              subItemList[j] = sum
            }
            newItemList[i] = subItemList
          }
          return Matrix.fromItemList(newItemList)
        }
        else {
          throw Error('矩阵无法相乘')
        }
      }

      // 获取矩阵的行列式
      getDeterminant () {
        if (this.m === this.n) {
          return Determinant.fromItemList(this.itemList)
        }
        else {
          throw Error('行列式格式错误')
        }
      }

      // 获取方阵的伴随矩阵
      getAdjugateMatrix () {
        const determinant = this.getDeterminant()
        const size = this.m
        const itemList = this.itemList
        const newItemList = JSON.parse(JSON.stringify(itemList))
        let i, j
        for (i = 0; i < size; i++) {
          for (j = 0; j < size; j++) {
            newItemList[j][i] = determinant.getCofactor(i, j)
          }
        }
        return Matrix.fromItemList(newItemList)
      }

      // 获取方阵的伴随矩阵
      getInverseMatrix () {
        const determinant = this.getDeterminant()
        const determinantValue = determinant.getValue()
        if (determinantValue === 0) {
          throw new Error('矩阵不可逆')
        }
        const value = 1 / determinantValue
        const size = this.m
        const itemList = this.itemList
        const newItemList = JSON.parse(JSON.stringify(itemList))
        let i, j
        for (i = 0; i < size; i++) {
          for (j = 0; j < size; j++) {
            newItemList[j][i] = Math.round(determinant.getCofactor(i, j) * value * 1000) / 1000
          }
        }
        return Matrix.fromItemList(newItemList)
      }

      // 获取行列式的值
      getValue (itemList) {
        itemList = itemList || this.itemList
        const size = itemList.length
        console.log(size, itemList)
        if (size === 1) {
          return itemList[0][0]
        }
        else if (size === 2) {
          return itemList[0][0] * itemList[1][1] - itemList[0][1] * itemList[1][0]
        }
        else if (size === 3) {
          return (
            itemList[0][0] * itemList[1][1] * itemList[2][2]
            + itemList[0][1] * itemList[1][2] * itemList[2][0]
            + itemList[0][2] * itemList[1][0] * itemList[2][1]
            - itemList[0][2] * itemList[1][1] * itemList[2][0]
            - itemList[0][0] * itemList[1][2] * itemList[2][1]
            - itemList[0][1] * itemList[1][0] * itemList[2][2]
          )
        }
        else if (size > 3) {
          let i = 0, sum = 0
          // 展开第一列
          for (i = 0; i < size; i++) {
            // aij * Aij
            sum += itemList[i][0] * Math.pow(-1, i) * this.getValue(this.getMinor(i, 0, itemList))
          }
          return sum
        }
      }

      // 根据字符串获取实例
      static fromArrayStr (str, m, n, order) {
        const numList = []
        str.split(',').forEach(v => v && numList.push(Number(v.trim())))
        if (!(m && n && m * n === numList.length)) {
          throw Error('矩阵格式错误')
        }
        return new Matrix(numList, m, n, order)
      }

      // 根据二维数组获取实例
      static fromItemList (itemList) {
        const matrix = new Matrix()
        matrix.itemList = itemList
        matrix.m = itemList.length
        matrix.n = itemList[0].length
        return matrix
      }
    }

    const btnTransposeEle = document.querySelector('#btn-transpose')
    const btnPlusEle = document.querySelector('#btn-plus')
    const btnMinusEle = document.querySelector('#btn-minus')
    const btnMultiplyEle = document.querySelector('#btn-multiply')
    const btnAdjugateEle = document.querySelector('#btn-adjugate')
    const btnInverseEle = document.querySelector('#btn-inverse')
    const eleM1 = document.querySelector('#m1')
    const eleN1 = document.querySelector('#n1')
    const eleM2 = document.querySelector('#m2')
    const eleN2 = document.querySelector('#n2')
    const btnValueEle = document.querySelector('#btn-value')
    const eleNumArray1 = document.querySelector('#input1')
    const eleNumArray2 = document.querySelector('#input2')
    const formulaEle = document.querySelector('#formula')
    const orderEleList = document.getElementsByName('order')

    // 渲染数学公式
    async function renderFormula (inputStr, onRender, onError) {
      MathJax.texReset()
      const options = MathJax.getMetricsFor(formulaEle)
      // options.display = true
      try {
        const node = await MathJax.tex2svgPromise(inputStr, options)
        formulaEle.appendChild(node)
        MathJax.startup.document.clear()
        MathJax.startup.document.updateDocument()
        onRender && onRender()
      } catch (e) {
        formulaEle.appendChild(document.createElement('pre')).appendChild(document.createTextNode(e.message))
        onError && onError()
      }
    }

    // 切换行（Direct3D）/列（OpenGL）主序
    let order = 'row'
    orderEleList[0].onchange = orderEleList[1].onchange = function () {
      order = this.value
    }

    // 矩阵转置
    btnTransposeEle.onclick = function () {
      const m1 = parseInt(eleM1.value.trim())
      const n1 = parseInt(eleN1.value.trim())
      const matrix1 = Matrix.fromArrayStr(eleNumArray1.value.trim(), m1, n1, order)
      const matrix2 = matrix1.getTransposedMatrix()
      // 打印数学公式
      const itemList1 = matrix1.itemList
      const itemList2 = matrix2.itemList
      const m2 = matrix2.m
      const n2 = matrix2.n
      const formulaSrcArray = ['A^T=\\begin{vmatrix}']
      let i, j, subArray
      for (i = 0; i < m1; i++) {
        subArray = []
        for (j = 0; j < n1; j++) {
          subArray.push(j < n1 - 1 ? `${itemList1[i][j]}&` : `${itemList1[i][j]}\\\\`)
        }
        formulaSrcArray.push(subArray.join(''))
      }
      formulaSrcArray.push('\\end{vmatrix}^T=\\begin{vmatrix}')
      for (i = 0; i < m2; i++) {
        subArray = []
        for (j = 0; j < n2; j++) {
          subArray.push(j < n2 - 1 ? `${itemList2[i][j]}&` : `${itemList2[i][j]}\\\\`)
        }
        formulaSrcArray.push(subArray.join(''))
      }
      formulaSrcArray.push('\\end{vmatrix}')
      formulaEle.innerHTML = ''
      const eleTriggerList = document.querySelectorAll('.trigger')
      eleTriggerList.forEach(ele => ele.disabled = true)
      renderFormula(formulaSrcArray.join(''),
        function () {
          eleTriggerList.forEach(ele => ele.disabled = false)
        },
        function () {
          eleTriggerList.forEach(ele => ele.disabled = false)
        })
    }
    // 矩阵相加减
    btnPlusEle.onclick = btnMinusEle.onclick = function () {
      const minus = this.id === 'btn-minus'
      const m1 = parseInt(eleM1.value.trim())
      const n1 = parseInt(eleN1.value.trim())
      const m2 = parseInt(eleM2.value.trim())
      const n2 = parseInt(eleN2.value.trim())
      const matrix1 = Matrix.fromArrayStr(eleNumArray1.value.trim(), m1, n1, order)
      const matrix2 = Matrix.fromArrayStr(eleNumArray2.value.trim(), m2, n2, order)
      const matrix3 = minus ? matrix1.minus(matrix2) : matrix1.plus(matrix2)
      const m3 = matrix3.m
      const n3 = matrix3.n
      // 打印数学公式
      const itemList1 = matrix1.itemList
      const itemList2 = matrix2.itemList
      const itemList3 = matrix3.itemList
      const formulaSrcArray = [`A${minus ? '-' : '+'}B = \\begin{vmatrix}`]
      let i, j, subArray
      for (i = 0; i < m1; i++) {
        subArray = []
        for (j = 0; j < n1; j++) {
          subArray.push(j < n1 - 1 ? `${itemList1[i][j]}&` : `${itemList1[i][j]}\\\\`)
        }
        formulaSrcArray.push(subArray.join(''))
      }
      formulaSrcArray.push(`\\end{vmatrix}${minus ? '-' : '+'}\\begin{vmatrix}`)
      for (i = 0; i < m2; i++) {
        subArray = []
        for (j = 0; j < n2; j++) {
          subArray.push(j < n2 - 1 ? `${itemList2[i][j]}&` : `${itemList2[i][j]}\\\\`)
        }
        formulaSrcArray.push(subArray.join(''))
      }
      formulaSrcArray.push(`\\end{vmatrix}=\\begin{vmatrix}`)
      for (i = 0; i < m3; i++) {
        subArray = []
        for (j = 0; j < n3; j++) {
          subArray.push(j < n3 - 1 ? `${itemList3[i][j]}&` : `${itemList3[i][j]}\\\\`)
        }
        formulaSrcArray.push(subArray.join(''))
      }
      formulaSrcArray.push(`\\end{vmatrix}`)
      formulaEle.innerHTML = ''
      const eleTriggerList = document.querySelectorAll('.trigger')
      eleTriggerList.forEach(ele => ele.disabled = true)
      renderFormula(
        formulaSrcArray.join(''),
        function () {
          eleTriggerList.forEach(ele => ele.disabled = false)
        },
        function () {
          eleTriggerList.forEach(ele => ele.disabled = false)
        }
      )
    }
    // 矩阵相乘
    btnMultiplyEle.onclick = function () {
      const m1 = parseInt(eleM1.value.trim())
      const n1 = parseInt(eleN1.value.trim())
      const m2 = parseInt(eleM2.value.trim())
      const n2 = parseInt(eleN2.value.trim())
      const matrix1 = Matrix.fromArrayStr(eleNumArray1.value.trim(), m1, n1, order)
      const matrix2 = Matrix.fromArrayStr(eleNumArray2.value.trim(), m2, n2, order)
      const matrix3 = matrix1.multiply(matrix2)
      const m3 = matrix3.m
      const n3 = matrix3.n
      // 打印数学公式
      const itemList1 = matrix1.itemList
      const itemList2 = matrix2.itemList
      const itemList3 = matrix3.itemList
      const formulaSrcArray = [`A×B = \\begin{vmatrix}`]
      let i, j, subArray
      for (i = 0; i < m1; i++) {
        subArray = []
        for (j = 0; j < n1; j++) {
          subArray.push(j < n1 - 1 ? `${itemList1[i][j]}&` : `${itemList1[i][j]}\\\\`)
        }
        formulaSrcArray.push(subArray.join(''))
      }
      formulaSrcArray.push(`\\end{vmatrix}×\\begin{vmatrix}`)
      for (i = 0; i < m2; i++) {
        subArray = []
        for (j = 0; j < n2; j++) {
          subArray.push(j < n2 - 1 ? `${itemList2[i][j]}&` : `${itemList2[i][j]}\\\\`)
        }
        formulaSrcArray.push(subArray.join(''))
      }
      formulaSrcArray.push(`\\end{vmatrix}=\\begin{vmatrix}`)
      for (i = 0; i < m3; i++) {
        subArray = []
        for (j = 0; j < n3; j++) {
          subArray.push(j < n3 - 1 ? `${itemList3[i][j]}&` : `${itemList3[i][j]}\\\\`)
        }
        formulaSrcArray.push(subArray.join(''))
      }
      formulaSrcArray.push(`\\end{vmatrix}`)
      formulaEle.innerHTML = ''
      const eleTriggerList = document.querySelectorAll('.trigger')
      eleTriggerList.forEach(ele => ele.disabled = true)
      renderFormula(
        formulaSrcArray.join(''),
        function () {
          eleTriggerList.forEach(ele => ele.disabled = false)
        },
        function () {
          eleTriggerList.forEach(ele => ele.disabled = false)
        }
      )
    }
    // 伴随矩阵
    btnAdjugateEle.onclick = function () {
      const m1 = parseInt(eleM1.value.trim())
      const n1 = parseInt(eleN1.value.trim())
      const matrix1 = Matrix.fromArrayStr(eleNumArray1.value.trim(), m1, n1, order)
      const matrix2 = matrix1.getAdjugateMatrix()
      // 打印数学公式
      const itemList1 = matrix1.itemList
      const itemList2 = matrix2.itemList
      const m2 = matrix2.m
      const n2 = matrix2.n
      const formulaSrcArray = ['A^*=\\begin{vmatrix}']
      let i, j, subArray
      for (i = 0; i < m1; i++) {
        subArray = []
        for (j = 0; j < n1; j++) {
          subArray.push(j < n1 - 1 ? `${itemList1[i][j]}&` : `${itemList1[i][j]}\\\\`)
        }
        formulaSrcArray.push(subArray.join(''))
      }
      formulaSrcArray.push('\\end{vmatrix}^*=\\begin{vmatrix}')
      for (i = 0; i < m2; i++) {
        subArray = []
        for (j = 0; j < n2; j++) {
          subArray.push(j < n2 - 1 ? `${itemList2[i][j]}&` : `${itemList2[i][j]}\\\\`)
        }
        formulaSrcArray.push(subArray.join(''))
      }
      formulaSrcArray.push('\\end{vmatrix}')
      formulaEle.innerHTML = ''
      const eleTriggerList = document.querySelectorAll('.trigger')
      eleTriggerList.forEach(ele => ele.disabled = true)
      renderFormula(formulaSrcArray.join(''),
        function () {
          eleTriggerList.forEach(ele => ele.disabled = false)
        },
        function () {
          eleTriggerList.forEach(ele => ele.disabled = false)
        })
    }
    // 矩阵求逆
    btnInverseEle.onclick = function () {
      const m1 = parseInt(eleM1.value.trim())
      const n1 = parseInt(eleN1.value.trim())
      const matrix1 = Matrix.fromArrayStr(eleNumArray1.value.trim(), m1, n1, order)
      const matrix2 = matrix1.getInverseMatrix()
      // 打印数学公式
      const itemList1 = matrix1.itemList
      const itemList2 = matrix2.itemList
      const m2 = matrix2.m
      const n2 = matrix2.n
      const formulaSrcArray = ['A^{-1}=\\begin{vmatrix}']
      let i, j, subArray
      for (i = 0; i < m1; i++) {
        subArray = []
        for (j = 0; j < n1; j++) {
          subArray.push(j < n1 - 1 ? `${itemList1[i][j]}&` : `${itemList1[i][j]}\\\\`)
        }
        formulaSrcArray.push(subArray.join(''))
      }
      formulaSrcArray.push('\\end{vmatrix}^{-1}=\\begin{vmatrix}')
      for (i = 0; i < m2; i++) {
        subArray = []
        for (j = 0; j < n2; j++) {
          subArray.push(j < n2 - 1 ? `${itemList2[i][j]}&` : `${itemList2[i][j]}\\\\`)
        }
        formulaSrcArray.push(subArray.join(''))
      }
      formulaSrcArray.push('\\end{vmatrix}')
      formulaEle.innerHTML = ''
      const eleTriggerList = document.querySelectorAll('.trigger')
      eleTriggerList.forEach(ele => ele.disabled = true)
      renderFormula(formulaSrcArray.join(''),
        function () {
          eleTriggerList.forEach(ele => ele.disabled = false)
        },
        function () {
          eleTriggerList.forEach(ele => ele.disabled = false)
        })
    }
  })()
</script>
</body>
</html>
